#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>

#include "StdTcp.h"
#include "StdThread.h"
#include "DoubleLinkList.h"
#include "ThreadPool.h"
#include "login.h"
#include "StdFile.h"

#define true 1
#define false 0

void SignalHandle(int signum);
struct Message
{
    int select;
    int operate;
    int accept;
    char fromName[20];
    char toName[20];
    char content[1024];
    char groupName[100];
    char Filecontent[1024];
    char fileName[100];
    size_t fileSize;
};
typedef struct Message Msg;

struct Client
{
    int sock;
    char name[20];
};
typedef struct Client C;

C *CreateClient(int sock, const char *name)
{
    C *c = (C *)malloc(sizeof(C));
    if (c == NULL)
    {
        printf("CreateClient malloc error\n");
        return NULL;
    }
    c->sock = sock;
    strcpy(c->name, name);
    return c;
}

void FreeClient(C *c)
{
    if (c != NULL)
    {
        free(c);
    }
}

DLlist list;

void *thread_handler(void *arg)
{
    int sock = *((int *)arg);
    while (1)
    {
        Msg msg = {0, 0, 0, 0, 0};
        TcpServerRecv(sock, &msg, sizeof(msg));
        if (msg.select == 1)
        {

            printf("用户[%s]已登录\n", msg.fromName);
            InsertTail(&list, CreateClient(sock, msg.fromName));
            InsertOnlineUser(msg.fromName);
        }

        else if (msg.select == 2)
        {
            if (msg.operate == 1)
            {
                printf("用户[%s]给用户[%s]发送了一条消息\n", msg.fromName, msg.toName);

                ChatRecordSaved(msg.fromName, msg.content, msg.toName);
                struct Node *travelPoint = list.head;
                while (travelPoint != NULL)
                {
                    C *c = (C *)travelPoint->data;
                    if (strcmp(c->name, msg.toName) == 0)
                    {
                        TcpServerSend(c->sock, &msg, sizeof(msg));
                        break;
                    }
                    travelPoint = travelPoint->next;
                }
            }
            else if (msg.operate == 2)
            {
                printf("用户[%s]群发了一条消息\n", msg.fromName);
                struct Node *travelPoint1 = list.head;
                while (travelPoint1 != NULL)
                {
                    C *c = (C *)travelPoint1->data;
                    if (strcmp(c->name, msg.fromName) != 0)
                    {
                        TcpServerSend(c->sock, &msg, sizeof(msg));
                    }
                    travelPoint1 = travelPoint1->next;
                }
            }
        }
        else if (msg.select == 4)
        {
            if (msg.operate == 2)
            {
                printf("[%s]给[%s]发送了一条加群申请\n", msg.fromName, msg.toName);
                struct Node *travelPoint2 = list.head;
                while (travelPoint2 != NULL)
                {
                    C *c = (C *)travelPoint2->data;
                    if (strcmp(c->name, msg.toName) == 0)
                    {
                        TcpServerSend(c->sock, &msg, sizeof(msg));
                        break;
                    }
                    travelPoint2 = travelPoint2->next;
                }
            }
            else if (msg.operate == 3)
            {
                insertGroupChat(msg.fromName, msg.content, msg.groupName);
                printf("[%s]在群[%s]发送了一条消息\n", msg.fromName, msg.groupName);

                DLlist *list2 = GetGroupMembers(msg.groupName);

                DLlist *list3 = FindGroupIntersection(&list, list2);

                struct Node *travelPoint3 = list3->head;
                while (travelPoint3 != NULL)
                {
                    C *c = (C *)travelPoint3->data;
                    TcpServerSend(c->sock, &msg, sizeof(msg));
                    travelPoint3 = travelPoint3->next;
                }
                FreeDLlist(list2);
                FreeDLlist(list3);
            }
            else if (msg.operate == 4)
            {
                printf("用户[%s]上传了群文件[%s],请打开群文件查看\n", msg.fromName, msg.fileName);
                char sql[1024] = {0};
                sprintf(sql, "./Group/GroupFile/%s/%s", msg.groupName, msg.fileName);
                int k = IsFileExist(sql);
                char newName[100];
                strcpy(newName, sql);
                while (k == true)
                {
                    strcpy(newName, ".");
                    char TargetName[100] = {0}; // 新建一个字符数组，用于分割
                    strcpy(TargetName, sql);

                    char *fileName = strtok(TargetName, ".");
                    char *backName = strtok(NULL, ".");

                    strcat(newName, fileName);
                    strcat(newName, "_new.");
                    strcat(newName, backName);
                    k = IsFileExist(newName);
                }
                WriteToFile(newName, msg.Filecontent, msg.fileSize);
            }
            else if (msg.operate == 5)
            {
                struct Node *travelPoint10 = list.head;
                while (travelPoint10 != NULL)
                {
                    C *c = (C *)travelPoint10->data;
                    if (strcmp(c->name, msg.toName) == 0)
                    {
                        TcpServerSend(c->sock, &msg, sizeof(msg));
                        break;
                    }
                    travelPoint10 = travelPoint10->next;
                }
            }
        }
        else if (msg.select == 5)
        {
            if (msg.operate == 1)
            {
                printf("用户[%s]给用户[%s]发送一个好友申请\n", msg.fromName, msg.toName);
                struct Node *travelPoint2 = list.head;
                while (travelPoint2 != NULL)
                {
                    C *c = (C *)travelPoint2->data;
                    if (strcmp(c->name, msg.toName) == 0)
                    {
                        TcpServerSend(c->sock, &msg, sizeof(msg));
                        break;
                    }
                    travelPoint2 = travelPoint2->next;
                }
            }
            else if (msg.operate == 2)
            {
                printf("用户[%s]给用户[%s]发送了一个文件\n", msg.fromName, msg.toName);

                struct Node *travelPoint3 = list.head;
                while (travelPoint3 != NULL)
                {
                    C *c = (C *)travelPoint3->data;
                    if (strcmp(c->name, msg.toName) == 0)
                    {
                        TcpServerSend(c->sock, &msg, sizeof(msg));
                        break;
                    }
                    travelPoint3 = travelPoint3->next;
                }
            }
            else if (msg.operate == 4)
            {
                struct Node *travelPoint10 = list.head;
                while (travelPoint10 != NULL)
                {
                    C *c = (C *)travelPoint10->data;
                    if (strcmp(c->name, msg.toName) == 0)
                    {
                        TcpServerSend(c->sock, &msg, sizeof(msg));
                        break;
                    }
                    travelPoint10 = travelPoint10->next;
                }
            }
        }

        else if (msg.select == 667)
        {
            DeleteOnlineUser(msg.fromName);

            sleep(1);
            printf("用户[%s]已下线\n", msg.fromName);
            pthread_exit(NULL);
        }
    }
}

int main(int argc, char **argv)
{
    signal(SIGINT, SignalHandle);
    if (argc != 3)
    {
        printf("invalid input\n");
        return -1;
    }

    InitDLlist(&list);
    ThreadP *p = InitThreadPool(10, 20, 10);
    if (p == NULL)
    {
        printf("threadp init error\n");
        return -1;
    }

    TcpS *s = InitTcpServer(argv[1], atoi(argv[2]));

    if (s == NULL)
    {
        printf("s is empty pointer\n");
        return -1;
    }
    int acceptSock = 0;

    while ((acceptSock = TcpServerAccept(s)) != -1)
    {
        ThreadP_AddTask(p, thread_handler, &acceptSock);
    }
    DestoryThreadPool(p);
    return 0;
}

void SignalHandle(int signum)
{
    FreeDLlist(&list);
    printf("程序已经正常退出\n");
    exit(0);
}